/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.kreig133.analytic.statistic;

import com.kreig133.analytic.interfaces.ViewDataHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 *
 * @author C.C.-fag
 */
public class PyramidMovingAverageHandler implements ViewDataHandler {

    private int koeff = 0;
    private ViewDataHandler previousHandler;
    private long[] binomNewtonKoeff;

    /**
     *
     * @param previousHandler - предшествующий обработчик
     * @param periodsCount - степень сглаживания (количество периодов).
     */
    public PyramidMovingAverageHandler(ViewDataHandler nextHandler) {
        this.previousHandler = nextHandler;
    }

    private static long factorial(int n) {
        if (n == 0 || n == 1) {
            return 1;
        }
        return n * factorial(n - 1);
    }

    public void setKoeff(Integer periodsCount) {
        if(this.koeff!=0 || periodsCount==0) return;
        
        this.koeff = periodsCount;
        this.binomNewtonKoeff = new long[periodsCount];
        
        if (periodsCount > 20) {//все что больше не влезет в long
            throw new IllegalArgumentException();
        }
        
        for (int i = 0; i < periodsCount; i++) {
            binomNewtonKoeff[i] = factorial(periodsCount) / (factorial(i) * factorial(periodsCount - i));
        }
    }

    public strictfp Map<Double, Double> getProcessedData() throws Exception {
        Map<Double, Double> temp = previousHandler.getProcessedData();
        Map<Double, Double> result = new TreeMap<Double, Double>() {
        };

        List<Double> list = new ArrayList<Double>();
        list.addAll(temp.keySet());
        Collections.sort(list);
        double sum = 0;
        double denominator = 0;
        for (int i = 0; i < binomNewtonKoeff.length; i++) {
            denominator += binomNewtonKoeff[i];
        }

        for (int i = 0; i < (list.size() - koeff); i++) {
            sum = 0;
            for (int j = 0; j < koeff; j++) {
                sum += binomNewtonKoeff[j] * temp.get(list.get(i + j));
            }
            result.put(list.get(i), sum / denominator);
        }
        return result;
    }

    public static void main(String[] args) {
        System.out.println(factorial(20));
    }
}
